﻿
namespace Sai.Core
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;

    // type change where includes "from" and "to"
    [Serializable]
    public sealed class BinaryTypeChange : IDiscoveredTypeChange, IEquatable<BinaryTypeChange>
    {
        // required for serialization
        public BinaryTypeChange()
        {
        }

        public BinaryTypeChange(TypeChangeReason reason, string message)
            : this (reason, null, null, message)
        {
        }

        public BinaryTypeChange(TypeChangeReason reason, IMessageProvider message)
            : this(reason, null, null, message)
        {
        }

        public BinaryTypeChange(TypeChangeReason reason, ISourceCodeProvider was, ISourceCodeProvider isNow)
            : this(reason, was, isNow, string.Empty)
        {
        }

        public BinaryTypeChange(TypeChangeReason reason, ISourceCodeProvider was, ISourceCodeProvider isNow, string message)
        {
            this.Reason = reason;
            this.Was = was == null ? null : was.ToCode();
            this.IsNow = isNow == null ? null : isNow.ToCode();
            this.Message = message;
        }

        public BinaryTypeChange(TypeChangeReason reason, ISourceCodeProvider was, ISourceCodeProvider isNow, IMessageProvider message)
            : this (reason, was, isNow, message.Message)
        {
        }

        public TypeChangeReason Reason { get; set; }

        public SourceCode Was { get; set; }

        public SourceCode IsNow { get; set; }

        public string Message { get; set; }

        public override int GetHashCode()
        {
            if (this.Was == null || this.IsNow == null)
                return this.Reason.GetHashCode() ^ this.Message.GetHashCode();

            return this.Reason.GetHashCode() 
                ^ this.Was.ToString().GetHashCode() 
                ^ this.IsNow.ToString().GetHashCode() 
                ^ this.Message.GetHashCode();
        }

        public override bool Equals(object obj)
        {
            if (obj == null)
            {
                return false;
            }

            BinaryTypeChange other = obj as BinaryTypeChange;

            if ((object)other == null)
            {
                return false;
            }

            return this.Reason == other.Reason
                && this.Was == other.Was
                && this.IsNow == other.IsNow
                && this.Message == other.Message;
        }

        public bool Equals(BinaryTypeChange other)
        {
            if ((object)other == null)
            {
                return false;
            }

            return this.Reason == other.Reason
                && this.Was == other.Was
                && this.IsNow == other.IsNow
                && this.Message == other.Message;
        }

        public static bool operator ==(BinaryTypeChange a, BinaryTypeChange b)
        {
            if (object.ReferenceEquals(a, b))
            {
                return true;
            }

            if (((object)a == null) || ((object)b == null))
            {
                return false;
            }

            return a.Reason == b.Reason
                && a.Was == b.Was
                && a.IsNow == b.IsNow
                && a.Message == b.Message;
        }

        public static bool operator !=(BinaryTypeChange a, BinaryTypeChange b)
        {
            return !(a == b);
        }
    }
}
